<?php
// +----------------------------------------------------------------------
// | 有小象汇 自研正版源码 赋能开发者
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 http://www.uxphp.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 有小象汇并不是自由软件，未经许可不能去掉有小象汇相关版权
// +----------------------------------------------------------------------
// | Author:  有小象汇
// +----------------------------------------------------------------------

namespace app\services\car;


use app\dao\car\CarInfoDao;
use app\model\car\CarInfo;
use app\model\car\CarOccupyTime;
use app\services\BaseServices;
use crmeb\exceptions\AdminException;
use think\exception\ValidateException;
use think\facade\Db;

/**
 * Class CarInfoServices
 * @package app\services\shendeng
 */
class CarInfoServices extends BaseServices
{
    public function __construct(CarInfoDao $dao)
    {
        $this->dao = $dao;
    }
    /**
     * 列表
     * @param array $where
     * @param string $field
     * @param bool $is_page
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList(array $where = [],string $field = '*',bool $is_page = false){
        $page = $limit = 0;
        if($is_page){
            [$page, $limit] = $this->getPageValue();
        }
        $list = $this->dao->getList($where,$field,$page,$limit);
        foreach ($list['list'] as &$item){
            $item['last_upkeep_date'] = $item['last_upkeep_date'] ? date('Y-m-d',$item['last_upkeep_date']) : '';
            $item['check_date'] = $item['check_date'] ? date('Y-m-d',$item['check_date']) : '';
            $item['insurance_date'] = $item['insurance_date'] ? date('Y-m-d',$item['insurance_date']) : '';
            $item['commercial_insurance_date'] = $item['commercial_insurance_date'] ? date('Y-m-d',$item['commercial_insurance_date']) : '';
        }
        return $list;
    }

    /**
     * 添加/修改保存
     * @param int $id
     * @param array $data
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function save(int $id, array $data){
        $info = $this->dao->getOne(['car_no' => $data['car_no'],'is_del'=>0]);
        if(isset($data['last_upkeep_date'])&&$data['last_upkeep_date']) $data['last_upkeep_date'] = strtotime($data['last_upkeep_date']);
        if(isset($data['check_date'])&&$data['check_date']) $data['check_date'] = strtotime($data['check_date']);
        if(isset($data['insurance_date'])&&$data['insurance_date']) $data['insurance_date'] = strtotime($data['insurance_date']);
        if(isset($data['commercial_insurance_date'])&&$data['commercial_insurance_date']) $data['commercial_insurance_date'] = strtotime($data['commercial_insurance_date']);
        if ($id) {
            if (!$this->dao->get($id)) throw new AdminException('数据不存在');
            if ($info && $id != $info['id']) throw new AdminException('该车辆信息已经存在');
            $data['up_time'] = time();
            if ($this->dao->update($id, $data)) {
                return true;
            } else {
                throw new AdminException('修改失败或者您没有修改什么');
            }
        } else {
            unset($data['id']);
            if ($info) throw new AdminException('该车辆信息已经存在');
            $data['add_time'] = time();
            $data['up_time'] = time();
            if ($this->dao->save($data)) {
                return true;
            } else {
                throw new AdminException('添加失败');
            }
        }
    }

    /**
     * 删除
     * @param int $id
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delInfo(int $id){
        $info = $this->dao->get($id);
        $this->check($info,"car");
        if ($info) {
            $data['is_del'] = 1;
            $data['delete_time'] = time();
            if (!$this->dao->update($id,$data)) {
                throw new AdminException('删除失败,请稍候再试!');
            }
        }
        return '删除成功!';
    }

    /**
     * 显示/隐藏
     * @param int $id
     * @param int $status
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function setShow(int $id, int $status){
        $info = $this->dao->getOne(['id' => $id,'is_del'=>0]);
        if (!$info){
            throw new AdminException('数据不存在');
        }
        if ($this->dao->update($id, ['status' => $status])) {
            return $status == 1 ? '显示成功' : '隐藏成功';
        } else {
            throw new AdminException($status == 1 ? '显示失败' : '隐藏失败');
        }
    }

    /**
     * 车辆信息批量删除
     * @param $ids
     * @return string
     */
    public function infoDelete($ids){
        $id = join(',',$ids);
        $data = ['is_del'=>1,'delete_time'=>time()];
        $res = CarInfo::where('id','in',$id)->save($data);
        if($res){
            return '删除成功';
        }else{
            throw new ValidateException('删除失败或你未选择数据');
        }
    }

    /**
     * 获取所有车辆信息
     * @return array
     */
    public function getCarInfoAll(){
        $model = new CarInfo();
        $model = $model->alias('ci')->where('ci.is_del','=',0)
            ->join('car_type ct','ct.id=ci.type_id')
            ->join('car_type_info ti','ti.id=ct.type_info_id','left')
            ->field('ci.id,ci.car_no,ti.type_name')
            ->select()->toArray();
        $car_info = [];
        foreach ($model as $item){
            $car_info[] = ['value'=>$item['id'],'label'=>$item['car_no']];
        }
        return $car_info;
    }

    /**
     * 获取车辆库存
     * @param $type_id
     * @param $stat_time
     * @param $end_time
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getCarInventory($type_id,$stat_time,$end_time){
        $car_info = CarInfo::where(['is_del'=>0,'type_id'=>$type_id,'car_status'=>1,'sxj_status'=>1])->select()->toArray();
        $inventory = 0;
        $car_no = [];
        $car_list = [];
        foreach ($car_info as $item){
            $is_inventory = false;
            $car_occupy_time = CarOccupyTime::where(['is_del'=>0,'car_id'=>$item['id']])->select()->toArray();
            foreach ($car_occupy_time as $occupy){
                 //$stat_time = 2024-05-29 16:00   $end_time =  2024-05-30 16:00
                // $occupy['start_time'] 2024-05-29 10:30:00   $occupy['end_time'] 2024-05-31 10:30:00
                if($stat_time <= $occupy['start_time'] && $end_time >= $occupy['start_time']){
                    $is_inventory = true;
                }
                if($stat_time<=$occupy['end_time']&& $end_time >= $occupy['end_time']){
                    $is_inventory = true;
                }
                if($stat_time>$occupy['start_time']&&$end_time < $occupy['end_time']){
                    $is_inventory = true;

                }
            }
            if(!$is_inventory){
                $inventory++;
                $car_no[] = $item['car_no'];
                $car_list[] = [
                  'id'=>$item['id'],
                  'car_no'=>$item['car_no'],
                  'img'=>$item['img'],
                ];
            }
        }
        // 返回可用库存车辆数量，车牌号
        return ['inventory'=>$inventory,'car_no'=>$car_no,'car_list'=>$car_list];
    }

    /**
     * 下单支付获取车辆库存
     * @param $type_id
     * @param $stat_time
     * @param $end_time
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getCarInventory2($type_id,$stat_time,$end_time,$car_id){
            $car_info = CarInfo::where(['is_del'=>0,'type_id'=>$type_id,'car_status'=>1,'sxj_status'=>1])->find();
            $car_occupy_time = CarOccupyTime::where(['is_del'=>0,'car_id'=>$car_id])->select()->toArray();
            foreach ($car_occupy_time as $occupy){
                if($stat_time <= $occupy['start_time'] && $end_time >= $occupy['start_time']){
                    throw new ValidateException('车辆已被预定，请重新下单！');
                }
                if($stat_time<=$occupy['end_time']&& $end_time >= $occupy['end_time']){
                    throw new ValidateException('车辆已被预定，请重新下单！');
                }
                if($stat_time>$occupy['start_time']&&$end_time < $occupy['end_time']){
                    throw new ValidateException('车辆已被预定，请重新下单！');
                }
            }
            return true;
    }

    /**
     * 获取门店车辆保养数及列表
     * @param int $place_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getUpkeepCar(int $place_id){
        // 下次保养日期(last_upkeep_date + ((upkeep_day-15) * 24 *3600))前15天提醒或公里数超出run_km > last_upkeep_km+upkeep_km 属于要保养
        $subQuery = Db::name('car_info')
            ->alias('a')
            ->leftJoin('car_type t', 'a.type_id = t.id')
            ->leftJoin('car_type_info i','t.type_info_id=i.id')
            ->where('a.is_del', 0)
            ->where('t.place_id', $place_id)
            ->field([
                'a.id',
                'from_unixtime(a.last_upkeep_date + ((a.upkeep_day - 15) * 24 * 3600), "%Y-%m-%d") as next_time',
                'a.last_upkeep_km + a.upkeep_km as next_km',
                'i.pic',
                'i.type_name',
                'i.gear',
                'i.seat_num',
                'i.power',
            ])->buildSql();
        $query = Db::name('car_info')
            ->alias('b')
            ->rightJoin([$subQuery => 'c'], 'b.id = c.id')
            ->where(function ($query) {
                $upkeep_start_time = date('Y-m-d',strtotime('-15 day',time()));
                $upkeep_end_time = date('Y-m-d',time());
                $query->whereBetween('c.next_time', [$upkeep_start_time, $upkeep_end_time])
                    ->whereOr('c.next_km', '<', Db::raw('b.run_km'));
            })
            ->field(['b.id','c.next_km','b.run_km','c.next_time','b.last_upkeep_date','c.pic','c.type_name','c.gear','c.seat_num','c.power','b.upkeep_day']);
        $list = $query->select()->toArray();
        $count = $query->count();
        foreach ($list as &$item){
            $item['last_upkeep_date'] = $item['last_upkeep_date'] ? date('Y-m-d',$item['last_upkeep_date']) : '暂无';
            $item['gear'] = $item['gear'] == 'auto' ? '自动挡' : '手动挡';
            $diff_time = get_difference_time(date('Y-m-d'),date('Y-m-d',strtotime('+15 day',strtotime($item['next_time']))));
            if($diff_time['days'] > 15){
                $km = (int)$item['run_km']-(int)$item['next_km'];
                $item['diff_text'] = '保养里程超出';
            }else{
                $item['diff_text'] = $diff_time['content'];
            }
        }
        return compact('list','count');
    }

    /**
     * 获取门店近期年检车辆列表及数量
     * @param int $place_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getAnnualCar(int $place_id){
        // 提前30天提醒，超过了也要提醒
        $lead_time = 3600*24*30; // 30天的时间
        $subQuery = Db::name('car_info')
            ->alias('i')
            ->leftJoin('car_type t', 'i.type_id=t.id')
            ->leftJoin('car_type_info ti','t.type_info_id=ti.id')
            ->where('i.is_del', 0)
            ->where('t.place_id', $place_id)
            ->field('i.id, i.check_date-'.$lead_time.' as lead_time,ti.pic,ti.type_name,ti.gear,ti.seat_num,ti.power')
            ->buildSql();
        $list = Db::name('car_info')
            ->alias('a')
            ->rightJoin([$subQuery => 'b'], 'a.id=b.id')
            ->where('b.lead_time', '<', time())
            ->field('a.id, b.lead_time,b.pic,b.type_name,b.gear,b.seat_num,b.power,a.check_date')
            ->select()->toArray();
        $count = count($list);
        foreach ($list as &$item){
            $item['check_date'] = $item['check_date'] ? date('Y-m-d',$item['check_date']) : '暂无';
            $item['gear'] = $item['gear'] == 'auto' ? '自动挡' : '手动挡';
            $diff_time = get_difference_time(date('Y-m-d'),$item['check_date']);
            $item['diff_text'] = $diff_time['content'];
        }
        return compact('list','count');
    }
    /**
     * 获取门店近期商业险车辆列表及数量
     * @param int $place_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getCommercialInsuranceCar(int $place_id){
        // 提前30天提醒，超过了也要提醒
        $lead_time = 3600*24*30; // 30天的时间
        $subQuery = Db::name('car_info')
            ->alias('i')
            ->leftJoin('car_type t', 'i.type_id=t.id')
            ->leftJoin('car_type_info ti','t.type_info_id=ti.id')
            ->where('i.is_del', 0)
            ->where('t.place_id', $place_id)
            ->field('i.id, i.commercial_insurance_date-'.$lead_time.' as lead_time,ti.pic,ti.type_name,ti.gear,ti.seat_num,ti.power')
            ->buildSql();
        $list = Db::name('car_info')
            ->alias('a')
            ->rightJoin([$subQuery => 'b'], 'a.id=b.id')
            ->where('b.lead_time', '<', time())
            ->field('a.id, b.lead_time,b.pic,b.type_name,b.gear,b.seat_num,b.power,a.commercial_insurance_date')
            ->select()->toArray();
        $count = count($list);
        foreach ($list as &$item){
            $item['commercial_insurance_date'] = $item['commercial_insurance_date'] ? date('Y-m-d',$item['commercial_insurance_date']) : '暂无';
            $item['gear'] = $item['gear'] == 'auto' ? '自动挡' : '手动挡';
            $diff_time = get_difference_time(date('Y-m-d'),$item['commercial_insurance_date']);
            $item['diff_text'] = $diff_time['content'];
        }
        return compact('list','count');
    }
    /**
     * 获取门店近期强险车辆列表及数量
     * @param int $place_id
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getInsuranceCar(int $place_id){
        // 提前30天提醒，超过了也要提醒
        $lead_time = 3600*24*30; // 30天的时间
        $subQuery = Db::name('car_info')
            ->alias('i')
            ->leftJoin('car_type t', 'i.type_id=t.id')
            ->leftJoin('car_type_info ti','t.type_info_id=ti.id')
            ->where('i.is_del', 0)
            ->where('t.place_id', $place_id)
            ->field('i.id, i.insurance_date-'.$lead_time.' as lead_time,ti.pic,ti.type_name,ti.gear,ti.seat_num,ti.power')
            ->buildSql();
        $list = Db::name('car_info')
            ->alias('a')
            ->rightJoin([$subQuery => 'b'], 'a.id=b.id')
            ->where('b.lead_time', '<', time())
            ->field('a.id, b.lead_time,b.pic,b.type_name,b.gear,b.seat_num,b.power,a.insurance_date')
            ->select()->toArray();
        $count = count($list);
        foreach ($list as &$item){
            $item['insurance_date'] = $item['insurance_date'] ? date('Y-m-d',$item['insurance_date']) : '暂无';
            $item['gear'] = $item['gear'] == 'auto' ? '自动挡' : '手动挡';
            $diff_time = get_difference_time(date('Y-m-d'),$item['insurance_date']);
            $item['diff_text'] = $diff_time['content'];
        }
        return compact('list','count');
    }

    /**
     * 获取车辆详情
     * @param int $car_id
     * @return array
     */
    public function getCarDetail(int $car_id){
        $info = CarInfo::alias('i')->where('i.id',$car_id)
            ->field('i.*,ti.type_name,ti.pic,ti.power,ti.gear,ti.seat_num,ti.oil_box')
            ->join('car_type t','i.type_id=t.id','left')
            ->join('car_type_info ti','t.type_info_id=ti.id','left')
            ->join('base_place p','t.place_id=p.id','left')
            ->find();
        $info = $info ? $info->toArray() : [];
        if(!$info) throw new ValidateException('未查询到车辆信息');
        $info['gear'] = $info['gear'] == 'auto' ? '自动挡' : '手动挡';
        return $info;
    }
}
